package com.shiyipicture.shiyipicturebackend.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shiyipicture.shiyipicturebackend.exception.BusinessException;
import com.shiyipicture.shiyipicturebackend.exception.ErrorCode;
import com.shiyipicture.shiyipicturebackend.exception.ThrowUtils;
import com.shiyipicture.shiyipicturebackend.model.dto.space.analyze.*;
import com.shiyipicture.shiyipicturebackend.model.entity.Picture;
import com.shiyipicture.shiyipicturebackend.model.entity.Space;
import com.shiyipicture.shiyipicturebackend.model.entity.User;
import com.shiyipicture.shiyipicturebackend.model.vo.space.analyze.*;
import com.shiyipicture.shiyipicturebackend.service.PictureService;
import com.shiyipicture.shiyipicturebackend.service.SpaceAnalyzeService;
import com.shiyipicture.shiyipicturebackend.service.SpaceService;
import com.shiyipicture.shiyipicturebackend.service.UserService;
import io.github.classgraph.json.JSONUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;


/**
 * 图片分析接口实现类
 */
@Service
@Slf4j
public class SpaceAnalyzeServiceImpl implements SpaceAnalyzeService {

  @Resource
  private UserService userService;

  @Resource
  private SpaceService spaceService;

  @Resource
  private PictureService pictureService;

  @Override
  public void checkSpaceAnalyzeAuth(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
    if (spaceAnalyzeRequest.isQueryAll() || spaceAnalyzeRequest.isQueryPublic()) {
      ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR, "权限不足");
    } else {
      Long spaceId = spaceAnalyzeRequest.getSpaceId();
      ThrowUtils.throwIf(spaceId == null || spaceId <= 0, ErrorCode.PARAMS_ERROR);
      Space space = spaceService.getById(spaceId);
      ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
      spaceService.checkSpaceAuth(loginUser, space);
    }
  }

  @Override
  public void fillAnalyzeQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest, QueryWrapper<Picture> queryWrapper) {
    ThrowUtils.throwIf(spaceAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
    Long spaceId = spaceAnalyzeRequest.getSpaceId();
    boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
    boolean queryAll = spaceAnalyzeRequest.isQueryAll();
    if (queryAll) {
      return;
    }
    if (queryPublic) {
      queryWrapper.isNull("spaceId");
      return;
    }
    if (spaceId != null) {
      queryWrapper.eq("spaceId", spaceId);
      return;
    }
    throw new BusinessException(ErrorCode.PARAMS_ERROR, "未指定查询范围");
  }

  /**
   * 获取空间使用分析数据
   *
   * @param spaceUsageAnalyzeRequest
   * @param loginUser
   * @return
   */
  @Override
  public SpaceUsageAnalyzeResponse getSpaceUsageAnalyze(SpaceUsageAnalyzeRequest spaceUsageAnalyzeRequest, User loginUser) {
    ThrowUtils.throwIf(spaceUsageAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
    if (spaceUsageAnalyzeRequest.isQueryAll() || spaceUsageAnalyzeRequest.isQueryPublic()) {
      this.checkSpaceAnalyzeAuth(spaceUsageAnalyzeRequest, loginUser);
      QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();
      pictureQueryWrapper.select("picSize");
      this.fillAnalyzeQueryWrapper(spaceUsageAnalyzeRequest, pictureQueryWrapper);
      List<Object> pictureObjectList = pictureService.getBaseMapper().selectObjs(pictureQueryWrapper);
      long resultSize = pictureObjectList.stream().mapToLong(result -> result instanceof Long ? (Long) result : 0L).sum();
      long resultCount = pictureObjectList.size();
      SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
      spaceUsageAnalyzeResponse.setUsedSize(resultSize);
      spaceUsageAnalyzeResponse.setMaxSize(null);
      spaceUsageAnalyzeResponse.setSizeUsageRatio(null);
      spaceUsageAnalyzeResponse.setUsedCount(resultCount);
      spaceUsageAnalyzeResponse.setMaxCount(null);
      spaceUsageAnalyzeResponse.setCountUsageRatio(null);
      return spaceUsageAnalyzeResponse;
    } else {
      Long spaceId = spaceUsageAnalyzeRequest.getSpaceId();
      ThrowUtils.throwIf(spaceId == null || spaceId <= 0, ErrorCode.PARAMS_ERROR);
      Space space = spaceService.getById(spaceId);
      ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");

      //权限校验
      spaceService.checkSpaceAuth(loginUser, space);

      SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
      spaceUsageAnalyzeResponse.setUsedSize(space.getTotalSize());
      spaceUsageAnalyzeResponse.setMaxSize(space.getMaxSize());
      double sizeUsageRatio = NumberUtil.round(space.getTotalSize() * 100.0 / space.getMaxSize(), 2).doubleValue();
      spaceUsageAnalyzeResponse.setSizeUsageRatio(sizeUsageRatio);
      spaceUsageAnalyzeResponse.setUsedCount(space.getTotalCount());
      spaceUsageAnalyzeResponse.setMaxCount(space.getMaxCount());
      double countUsageRatio = NumberUtil.round(space.getTotalCount() * 100.0 / space.getMaxCount(), 2).doubleValue();
      spaceUsageAnalyzeResponse.setCountUsageRatio(countUsageRatio);
      return spaceUsageAnalyzeResponse;
    }

  }

  @Override
  public List<SpaceUserAnalyzeResponse> getSpaceUserAnalyze(SpaceUserAnalyzeRequest spaceUserAnalyzeRequest, User loginUser) {
    ThrowUtils.throwIf(spaceUserAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
    checkSpaceAnalyzeAuth(spaceUserAnalyzeRequest, loginUser);
    QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();
    Long userId = loginUser.getId();
    pictureQueryWrapper.eq(ObjectUtil.isNotNull(userId), "userId", userId);
    fillAnalyzeQueryWrapper(spaceUserAnalyzeRequest, pictureQueryWrapper);

    //分析维度
    String timeDimension = spaceUserAnalyzeRequest.getTimeDimension();
    switch (timeDimension) {
      case "day":
        pictureQueryWrapper.select("DATE_FORMAT(createTime,'%Y-%m-%d') as period", "count(*) as count");
        break;
      case "week":
        pictureQueryWrapper.select("YEARWEEK(createTime) as period", "count(*) as count");
        break;
      case "month":
        pictureQueryWrapper.select("DATE_FORMAT(createTime,'%Y-%m') as period", "count(*) as count");
        break;
      default:
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "不存在的时间维度");
    }

    pictureQueryWrapper.groupBy("period").orderByDesc("period");

    //查询结果并转换
    List<Map<String, Object>> queryResult = pictureService.getBaseMapper().selectMaps(pictureQueryWrapper);
    return queryResult.stream().map(result -> {
      SpaceUserAnalyzeResponse spaceUserAnalyzeResponse = new SpaceUserAnalyzeResponse();
      spaceUserAnalyzeResponse.setPeriod(result.get("period").toString());
      spaceUserAnalyzeResponse.setCount(result.get("count") == null ? 0L : Long.parseLong(result.get("count").toString()));
      return spaceUserAnalyzeResponse;
    }).collect(Collectors.toList());
  }

  /**
   * 根据图片分类查进行图片分类分析
   *
   * @param spaceCategoryAnalyzeRequest
   * @param loginUser
   * @return
   */
  @Override
  public List<SpaceCategoryAnalyzeResponse> getSpaceCategoryAnalyze(SpaceCategoryAnalyzeRequest spaceCategoryAnalyzeRequest, User loginUser) {
    ThrowUtils.throwIf(spaceCategoryAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

    checkSpaceAnalyzeAuth(spaceCategoryAnalyzeRequest, loginUser);

    QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();
    fillAnalyzeQueryWrapper(spaceCategoryAnalyzeRequest, pictureQueryWrapper);
    pictureQueryWrapper.select("category AS category", "COUNT(*) AS count", "SUM(picSize) AS totalSize ")
      .groupBy("category");

    return pictureService.getBaseMapper().selectMaps(pictureQueryWrapper).stream().map(result -> {
      SpaceCategoryAnalyzeResponse spaceCategoryAnalyzeResponse = new SpaceCategoryAnalyzeResponse();
      spaceCategoryAnalyzeResponse.setCategory(result.get("category").toString());
      spaceCategoryAnalyzeResponse.setCount(Long.parseLong(result.get("count").toString()));
      spaceCategoryAnalyzeResponse.setTotalSize(Long.parseLong(result.get("totalSize").toString()));
      return spaceCategoryAnalyzeResponse;
    }).collect(Collectors.toList());
  }

  /**
   * 获取空间标签分析
   *
   * @param spaceTagAnalyzeRequest
   * @param loginUser
   * @return
   */
  @Override
  public List<SpaceTagAnalyzeResponse> getSpaceTagAnalyze(SpaceTagAnalyzeRequest spaceTagAnalyzeRequest, User loginUser) {
    ThrowUtils.throwIf(spaceTagAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

    checkSpaceAnalyzeAuth(spaceTagAnalyzeRequest, loginUser);

    QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();
    fillAnalyzeQueryWrapper(spaceTagAnalyzeRequest, pictureQueryWrapper);

    pictureQueryWrapper.select("tags");
    List<String> tagsJsonList = pictureService.getBaseMapper().selectObjs(pictureQueryWrapper)
      .stream().filter(ObjectUtil::isNotEmpty)
      .map(Object::toString)
      .collect(Collectors.toList());
    Map<String, Long> tagCountMap = tagsJsonList.stream().flatMap(tagsJson -> JSONUtil.toList(tagsJson, String.class).stream())
      .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));

    return tagCountMap.entrySet().stream().sorted((e1, e2) -> Long.compare(e2.getValue(), e1.getValue()))
      .map(entry -> new SpaceTagAnalyzeResponse(entry.getKey(), entry.getValue())).collect(Collectors.toList());
  }

  /**
   * 分析图片大小范围及其数量
   * @param spaceSizeAnalyzeRequest
   * @param loginUser
   * @return
   */
  @Override
  public List<SpaceSizeAnalyzeResponse> getSpaceSizeAnalyze(SpaceSizeAnalyzeRequest spaceSizeAnalyzeRequest, User loginUser) {
    ThrowUtils.throwIf(spaceSizeAnalyzeRequest == null,ErrorCode.PARAMS_ERROR);

    checkSpaceAnalyzeAuth(spaceSizeAnalyzeRequest, loginUser);

    QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();
    fillAnalyzeQueryWrapper(spaceSizeAnalyzeRequest, pictureQueryWrapper);

    pictureQueryWrapper.select("picSize");

    List<Long> picSizes = pictureService.getBaseMapper().selectObjs(pictureQueryWrapper)
      .stream().map(obj -> (Long) obj).collect(Collectors.toList());

    LinkedHashMap<String, Long> sizeRanges = new LinkedHashMap<>();
    sizeRanges.put("<100KB", picSizes.stream().filter(size -> size < 100 * 1024).count());
    sizeRanges.put("100KB-500KB", picSizes.stream().filter(size -> size >= 100 * 1024 && size < 500 * 1024).count());
    sizeRanges.put("500KB-1MB", picSizes.stream().filter(size -> size >= 500 * 1024 && size < 1 * 1024 * 1024).count());
    sizeRanges.put(">1MB", picSizes.stream().filter(size -> size >= 1 * 1024 * 1024).count());

   return sizeRanges.entrySet().stream().map(entry -> new SpaceSizeAnalyzeResponse(entry.getKey(), entry.getValue()))
     .collect(Collectors.toList());
  }

  /**
   * 查看空间排行
   * @param spaceRankAnalyzeRequest
   * @param loginUser
   * @return
   */
  @Override
  public List<Space> getSpaceRankAnalyze(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest, User loginUser) {
    ThrowUtils.throwIf(spaceRankAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

    if (!userService.isAdmin(loginUser)) {
      throw new BusinessException(ErrorCode.NO_AUTH_ERROR,"无权查看空间排行");
    }

    QueryWrapper<Space> spaceQueryWrapper = new QueryWrapper<>();
    spaceQueryWrapper.select("id", "spaceName", "userId", "totalSize")
      .orderByDesc("totalSize")
      .last("LIMIT " + spaceRankAnalyzeRequest.getTopN()); // 取前 N 名

    // 查询结果
    return spaceService.list(spaceQueryWrapper);
  }

}
